<script setup lang="ts">
import { ref, computed } from 'vue'
import { useMessage } from 'naive-ui'

const message = useMessage()
const jsonInput = ref('')
const delimiter = ref(',')
const error = ref('')

const delimiterOptions = [
  { label: '逗号 (,)', value: ',' },
  { label: '分号 (;)', value: ';' },
  { label: '制表符 (Tab)', value: '\t' }
]

const sampleData = [
  {
    "id": 1,
    "name": "张三",
    "age": 25,
    "email": "zhangsan@example.com",
    "hobbies": ["读书", "游泳"]
  },
  {
    "id": 2,
    "name": "李四",
    "age": 30,
    "email": "lisi@example.com",
    "hobbies": ["篮球", "音乐"]
  }
]

const loadSample = () => {
  jsonInput.value = JSON.stringify(sampleData, null, 2)
  error.value = ''
}

const csvOutput = computed(() => {
  try {
    if (!jsonInput.value.trim()) {
      return ''
    }

    const data = JSON.parse(jsonInput.value)
    if (!Array.isArray(data) || data.length === 0) {
      throw new Error('JSON 必须是一个非空数组')
    }

    // 获取所有可能的列
    const columns = new Set<string>()
    data.forEach(item => {
      Object.keys(item).forEach(key => columns.add(key))
    })
    const headerRow = Array.from(columns)

    // 创建 CSV 行
    const rows = [
      // 表头
      headerRow.join(delimiter.value),
      // 数据行
      ...data.map(item => 
        headerRow.map(column => {
          const value = item[column]
          if (value === null || value === undefined) {
            return ''
          }
          if (Array.isArray(value)) {
            return '"' + value.join(';') + '"'
          }
          if (typeof value === 'object') {
            return '"' + JSON.stringify(value) + '"'
          }
          if (typeof value === 'string' && (value.includes(delimiter.value) || value.includes('"') || value.includes('\n'))) {
            return '"' + value.replace(/"/g, '""') + '"'
          }
          return value
        }).join(delimiter.value)
      )
    ]

    error.value = ''
    return rows.join('\n')
  } catch (err) {
    error.value = err instanceof Error ? err.message : '无效的 JSON 格式'
    return ''
  }
})

const copyToClipboard = async () => {
  try {
    await navigator.clipboard.writeText(csvOutput.value)
    message.success('CSV 已复制到剪贴板')
  } catch (err) {
    message.error('复制失败，请手动复制')
  }
}

const downloadCsv = () => {
  const blob = new Blob([csvOutput.value], { type: 'text/csv;charset=utf-8;' })
  const link = document.createElement('a')
  link.href = URL.createObjectURL(blob)
  link.download = 'data.csv'
  link.click()
  URL.revokeObjectURL(link.href)
  message.success('CSV 文件已开始下载')
}
</script>

<template>
  <div class="p-4 mx-auto max-w-7xl">
    <n-card>
      <template #header>
        <div class="text-2xl font-bold">JSON 转 CSV</div>
        <p class="mt-2 text-sm text-gray-600 dark:text-gray-400">将 JSON 数组转换为 CSV 格式，支持自定义分隔符</p>
      </template>

      <div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
        <!-- JSON 输入区 -->
        <div class="space-y-4">
          <div class="flex items-center justify-between">
            <h3 class="font-medium">JSON 输入</h3>
            <n-button
              tertiary
              type="primary"
              size="small"
              @click="loadSample"
            >
              加载示例
            </n-button>
          </div>
          <n-input
            v-model:value="jsonInput"
            type="textarea"
            :autosize="{ minRows: 15, maxRows: 15 }"
            placeholder="请输入 JSON 数组..."
            :status="error ? 'error' : undefined"
          />
          <div v-if="error" class="text-sm text-red-500">{{ error }}</div>
        </div>

        <!-- CSV 输出区 -->
        <div class="space-y-4">
          <div class="flex items-center justify-between">
            <h3 class="font-medium">CSV 输出</h3>
            <div class="flex items-center gap-2">
              <n-select
                v-model:value="delimiter"
                :options="delimiterOptions"
                size="small"
                style="width: 120px"
              />
              <n-button
                type="primary"
                size="small"
                :disabled="!csvOutput"
                @click="copyToClipboard"
              >
                复制
              </n-button>
              <n-button
                type="success"
                size="small"
                :disabled="!csvOutput"
                @click="downloadCsv"
              >
                下载
              </n-button>
            </div>
          </div>
          <n-input
            :value="csvOutput"
            type="textarea"
            :autosize="{ minRows: 15, maxRows: 15 }"
            readonly
          />
        </div>
      </div>
    </n-card>
  </div>
</template>

<style scoped>
:deep(.n-input) {
  font-family: monospace;
}
</style> 